package ctrhost

import (
    "github.com/astaxie/beego/logs"
    "fmt"
    "path/filepath"
    "plugin"
    "net/url"
    "strings"
    "cloud_worm/util/umodels/mysqldb"
    "cloud_worm/util/umodels/mysqldb/dbdata"
    "cloud_worm/util/uhttp"
    "cloud_worm/wormweb/controllers/ctrconfig"
    "cloud_worm/wormweb/controllers/ctrutil"
)

// todo: 展示优化的方向：
// 1. 可以提供统计结果输出；
// 2. 可以提供查看触发实时获取；

// machine的详细信息
type MachineDetailController struct {
    ctrconfig.LoginCtr
}

// @Description: 描述信息的list
type DetailListData struct {
    Ip          string
    Name        string
    Nickname    string
    Count       int
    Updated     int64
}

// MachineDetailController.DetailList 主机信息的list
func (m *MachineDetailController) DetailList() {
    m.Manager()

    ip := m.GetString("ip", mysqldb.SelectStrAll)
    if ip == mysqldb.SelectStrAll {
        logs.Error(fmt.Sprintf("input ip error."))
        data := map[string]interface{}{"total": 0, "data": []*DetailListData{}}
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input ip error.", data)
        m.ServeJSON()
        return
    }

    status, err := m.GetInt("status", mysqldb.StatusAll)

    mi := &dbdata.MachineInfo{}
    count, err := mi.SelectCount(status, ip)
    if err != nil {
        logs.Error(fmt.Sprintf("select count for '%s' error.", ip))
        data := map[string]interface{}{"total": 0, "data": []*DetailListData{}}
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "select count error.", data)
        m.ServeJSON()
        return
    }

    mis, err := mi.Select(mysqldb.SelectOffsetZero, mysqldb.SelectLimitAll, status, ip)
    if err != nil {
        logs.Error(fmt.Sprintf("select for '%s' error.", ip))
        data := map[string]interface{}{"total": 0, "data": []*DetailListData{}}
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "select error.", data)
        m.ServeJSON()
        return
    }
    var listData []*DetailListData
    for _, item := range mis {
        listData = append(listData, &DetailListData{
            Ip: item.Ip,
            Name: item.Name,
            Nickname: item.Nickname,
            Count: item.Count,
            Updated: item.Updated,
        })
    }

    data := map[string]interface{}{"total": count, "data": listData}
    m.Data["json"] = uhttp.CreateOkResponse(data)
    m.ServeJSON()
    return
}

// MachineDetailController.parseURIForNameDetail 读取具体子项的详细信息
func (m *MachineDetailController) parseURIForNameDetail() (string, error) {
    u, err := url.Parse(m.Ctx.Request.URL.EscapedPath())
    if err != nil {
        return "", err
    }
    inputURI := u.Path

    elems := strings.Split(inputURI, "/")
    if len(elems) <= 0 {
        return "", fmt.Errorf("input url error: %s", inputURI)
    }

    name := elems[len(elems) - 1]
    return name, nil
}

// MachineDetailController.NameDetail 读取子项的详细信息
func (m *MachineDetailController) NameDetail() {
    m.Manager()

    ip := m.GetString("ip", mysqldb.SelectStrAll)
    if ip == mysqldb.SelectStrAll {
        logs.Error(fmt.Sprintf("input ip error."))
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input ip error.", nil)
        m.ServeJSON()
        return
    }

    name, err := m.parseURIForNameDetail()
    if err != nil {
        logs.Error(fmt.Sprintf("input name error."))
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeParamErr, "input ip error.", nil)
        m.ServeJSON()
        return
    }

    mi := &dbdata.MachineInfo{
        Ip: ip,
        Name: name,
    }
    err = mi.Read("ip", "name")
    if err != nil {
        logs.Error(fmt.Sprintf("read record for '%s' '%s' error: %s", ip, name, err.Error()))
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "read record error.", nil)
        m.ServeJSON()
        return
    }

    soPath := filepath.Join(ctrutil.UploadSoDir, name + ".so")
    p, err := plugin.Open(soPath)
    if err != nil {
        logs.Error(fmt.Sprintf("open lib`%s` so error: %s", name, err.Error()))
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "open lib so.", nil)
        m.ServeJSON()
        return
    }

    // get function
    f, err := p.Lookup(ctrutil.GetOutputFunc)
    if err != nil {
        logs.Error(fmt.Sprintf("lookup getoutput function error: %s", err.Error()))
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "lookup getoutput function error.", nil)
        m.ServeJSON()
        return
    }

    data, err := f.(func(string)(interface{}, error))(mi.Detail)
    if err != nil {
        logs.Error(fmt.Sprintf("do getput function error: %s", err.Error()))
        m.Data["json"] = uhttp.CreateErrResponse(uhttp.RespCodeSystemErr, "do getoutput function error.", nil)
        m.ServeJSON()
        return
    }

    m.Data["json"] = uhttp.CreateOkResponse(data)
    m.ServeJSON()
    return
}